#pragma once
#include <sys/socket.h>
#include <iostream>
#include <netinet/in.h>
#include <time.h>
#include <functional>
// 写一个时间堆    依靠堆的性质来实现定时器的效果
#define CLIENT_BUFFER 1024
struct client_data;
struct timer;
using func_t = std::function<void(client_data *)>;


struct client_data // 记录客户端的信息
{

    void setsockfd(int _sockfd)
    {
        sockfd = _sockfd;
    }

    
    void setsockaddr_in(sockaddr_in _addr)
    {
        addr = _addr;
    }

    sockaddr_in addr;
    int sockfd;
    char buffer[CLIENT_BUFFER]; // 用户缓冲区，用来接收数据
    timer *client_timer;
};

struct timer // 定时器对象
{
    timer(int delay)
    {
        _expire = time(NULL) + delay;
    }

    void setfunc(func_t _handler)
    {
        handler = _handler;
    }



    bool operator>(const timer &rhs) const
    {
        return _expire > rhs._expire;
    }

    bool operator<(const timer &rhs) const
    {
        return _expire < rhs._expire;
    }

    time_t _expire; // 绝对超时时间
    client_data *_client_data;
    func_t handler; // 定时回调处理函数，接收一个client_data的指针
};

void handler(client_data *cli)
{
    std::cout << "void handler(client_data*)" << std::endl;
    return;
}


/// 主要目标，支持insert一个定时器节点(完成扩容接口)    支持传入一个timer**a指针构造堆
/// 1.向下调整   向上调整    pop移除倒时的定时器   top获取下一次到时的定时器对象
/// 主要用小堆的绝对超时时间作为下一次调用的时间
class Timer_Heap
{
public:
    Timer_Heap(int cap) : capacity(cap)
    {
        Timer_array = new timer *[capacity]; // 创建数组，数组内部存储的是一个一个指向定时器对象的指针
        for (int i = 0; i < capacity; i++)
        {
            Timer_array[i] = nullptr;
        }
    }
    Timer_Heap(timer **Timer_array1, int capacity1, int size1)
    {
        // 传入一个定时器指针数组
        Timer_array = new timer *[capacity1];
        capacity = capacity1;
        size = size1;
        for (int i = 0; i < capacity; i++)
        {
            Timer_array[i] = Timer_array1[i];
        }

        // TODO  进行向下调整构成堆
        int i = (size - 1 - 1) / 2;
        for (; i >= 0;)
        {
            adjustdown(i, size); // 进行向下建堆
            i--;
        }
    }

    // 只负责循环检查到期的定时器，定时时间由下层设置
    void Handler_heap_timer() // func_t是每个定时器的回调函数，用来处理用户的连接以及后续工作   handler是信号的处理函数中的部分
    {
        time_t test_time = time(NULL);
        // 循环检测，直到出现不到期的定时器，设置为堆顶
        while (!empty())
        {
            //std::cout << " void Handler_heap_timer()" << std::endl;
            if (HeapTop()->_expire < test_time)
            {
                break;
            }
            else if (HeapTop()->_expire >= test_time)
            {

                // 说明此时定时器失效,调用定时器回调函数
                HeapTop()->handler(HeapTop()->_client_data);
                // 进行删除以及重新生成堆
                Heapdel();
            }
        }
    }

    bool empty()
    {
        return size == 0;
    }

    void HeapInsert(timer *Timer)
    {
        Timer_array[size] = Timer;
        adjustup(); // 进行向上调整算法，将最小的定时器expire置于堆顶
        std::cout << "void HeapInsert(timer *Timer)" << std::endl;
        // 插入完的时候进行判断
        size++;
        Expansion();
    }

    void HeapPop()
    {
        Heapdel();
    }

    timer *HeapTop()
    {
        return Timer_array[0];
    }

    ~Timer_Heap() // 析构
    {
        for (int i = 0; i < size; i++)
        {
            delete Timer_array[i];
        }
        delete[] Timer_array;
    }

private:
    void Heapdel() // 进行堆顶的删除
    {
        if (!empty())
        {
            // 将堆顶和最后一个元素进行交换
            std::swap(Timer_array[0], Timer_array[size - 1]);

            // 新的堆顶进行向下调整
            adjustdown(0, size);
            size--;
        }
    }

    void adjustup() // 向上调整算法   用于新添一个定时器对象  堆结构进行调整
    {
        int child = size - 1;
        while (child > 0)
        {
            int parent = (child - 1) / 2;
            if (Timer_array[parent] > Timer_array[child]) // 如果父节点小于子节点
            {
                std::swap(Timer_array[parent], Timer_array[child]); // 交换父节点和子节点
                child = parent;                                     // 继续检查新的父节点
            }
            else
            {
                break; // 退出循环
            }
        }
    }

    void adjustdown(int parent, int n1) // 这里的parent是向下调整开始的位置，n1是这次调整的总的数据个数
    {
        int child = 2 * parent + 1;

        while (child < n1)
        {
            // 选取孩子中较小的那个

            if (((child + 1) < n1) && Timer_array[child] > Timer_array[child + 1])
            {
                child++;
            }
            if (Timer_array[child] < Timer_array[parent])
            {
                std::swap(Timer_array[parent], Timer_array[child]); // 交换父节点和子节点

                parent = child;
                child = parent * 2 + 1;
            }
            else
            {
                // std::cout<<"child:"<<child<<std::endl;
                break;
            }
        }
    }
    void Expansion() // 用来在插入定时器的时候，空间不够进行扩容
    {
        if (capacity == size)
        {
            capacity = capacity == 0 ? 1 : capacity * 2;
            timer **Timer_array_1 = new timer *[capacity];
            if (Timer_array_1 == nullptr)
            {
                std::cout << "Timer_array_1==nullptr" << std::endl;
                return;
            }

            for (int i = 0; i < capacity; i++)
            {
                Timer_array_1[i] = nullptr; // 初始化新的数组
            }
            for (int i = 0; i < size; i++)
            {
                Timer_array_1[i] = Timer_array[i];
            }
            Timer_array = Timer_array_1;
        }
    }

    timer **Timer_array; // 数组指针，指向的是数组首元素，而不是整个数组，因为内存中也不存在数组
    int capacity;
    int size; // 堆中的元素个数
};
